package programme;
/**
 * Classe implémentant une contrainte d'un programme.<br />
 * Une contrainte est de la forme suivante : {expression} {type} {borne}.<br />
 * <em>Exemple : </em><br />La contrainte x1 + 3*x2 + 10*x3 < 9 est modélisée par : 
 * <ul>
 * <li>Expression : x1 + 3*x2 + 10*x3</li>
 * <li>Type : &lt; (INF) </li>
 * <li>Borne : 9</li>
 * </ul>
 * 
 * 
 */
public class Contrainte {

	/** Type de comparaison entre le premier et le second membre de la contrainte.<br />
	 * <em>par exemple : </em>inférieure, supérieure, égale...
	 */
	private TypeContrainte type;
	
	/** Expression du premier membre de la contrainte */
	private Expression expression;
	
	/** Second membre de la contrainte */
	private double borne;
	
	/** Indique si la contrainte est relaxée, dans le cas où elle l'est, 
	 * elle n'est pas à prendre en compte dans la résolution du PL */
	private boolean relax;

	public Contrainte(Expression expression, TypeContrainte type, double borne,
			boolean relax) {
		super();
		this.expression = expression;
		this.type = type;
		this.borne = borne;
		this.relax = relax;
	}
	
	public TypeContrainte getType() {
		return type;
	}

	public void setType(TypeContrainte type) {
		this.type = type;
	}

	public Expression getExpression() {
		return expression;
	}

	public void setExpression(Expression expression) {
		this.expression = expression;
	}

	public double getBorne() {
		return borne;
	}

	public void setBorne(double borne) {
		this.borne = borne;
	}

	public boolean isRelax() {
		return relax;
	}

	public void setRelax(boolean relax) {
		this.relax = relax;
	}
	
	/**
	 * Méthode d'évaluation d'un jeu de valeurs sur une contrainte
	 * 
	 * @param s	Le jeu de valeur
	 * @return	La valeur de l'expression de la contrainte
	 */
	private double eval(Solution s){
		
		double resultat = 0;
		double element;
		
		for (SousExpression se : expression.getSsExpressions()){
			
			element = se.getCoef();
			
			for (Variable v : se.getVar()){
				
				element *= s.getValeurs().get(v);
				
			}
			
			resultat += element;
			
		}
		
		return resultat;
	}
	
	/**
	 * Méthode déterminant si une contrainte est satisfaite par un jeu de valeurs
	 * @param s	Le jeu de valeur
	 * @return	La valeur de l'expression de la contrainte
	 */
	public boolean estSatisfaitePar(Solution solution){
		
		if (type.equals(TypeContrainte.EGAL)){
			return ( eval(solution) == borne );
		}
		else if (type.equals(TypeContrainte.INF)){
			return ( eval(solution) <= borne );
		}
		else if (type.equals(TypeContrainte.SUP)){
			return ( eval(solution) >= borne );
		}
		return false;
		
	}
	
	@Override
	public String toString() {
		
		String res = "";
		
		for (SousExpression se : expression.getSsExpressions()){
			
			res += se.coef + " . ";
			
			for (Variable v : se.getVar()){
				
				// element *= s.getValeurs().get(v);
				res += v + " . ";
				
			}
			
			res += " + ";
			
		}
		
		res += type + " " + borne;
		
		return res;
	}
	
	public String toString(Solution s) {
		
		String res = "";
		
		for (SousExpression se : expression.getSsExpressions()){
			
			res += se.coef + " . ";
			
			for (Variable v : se.getVar()){
				
				// element *= s.getValeurs().get(v);
				res += v + " (" + s.getValeurs().get(v) + ") ";
				
			}
			
			res += " + ";
			
		}
		
		res += type + " " + borne;
		
		return res;
	}

}
